package com.badlogic.androidgames.framework.impl;

import java.util.ArrayList;
import java.util.List;

import android.view.MotionEvent;
import android.view.View;

import com.androidgame.framwork.Input.TouchEvent;
import com.badlogic.androidgames.framework.impl.Pool.PoolObjectFactory;

public class MultiTouchHandler implements TouchHandler{

	boolean[] isTouched = new boolean[20];
	int[] touchX = new int[20];
	int[] touchY = new int[20];
	Pool<TouchEvent> touchEventPool;
	List<TouchEvent> touchEvents = new ArrayList<TouchEvent>();
	List<TouchEvent> touchEventBuffer = new ArrayList<TouchEvent>();
	float scaleX;
	float scaleY;
	
	public MultiTouchHandler(View view, float scaleX, float scaleY)
	{
		PoolObjectFactory<TouchEvent> factory = new PoolObjectFactory<TouchEvent>()
		{

			@Override
			public TouchEvent createObject() {
				// TODO Auto-generated method stub
				return new TouchEvent();
			}
		};
		touchEventPool = new Pool<TouchEvent>(factory, 100);
		view.setOnTouchListener(this);
		
		this.scaleX = scaleX;
		this.scaleY = scaleY;
	}
	
	@Override
	public boolean onTouch(View arg0, MotionEvent arg1) {
		// TODO Auto-generated method stub
		synchronized(this)
		{
			int action = arg1.getAction() & MotionEvent.ACTION_MASK;
			int pointerIndex = (arg1.getAction() & MotionEvent.ACTION_POINTER_ID_MASK) >> MotionEvent.ACTION_POINTER_ID_SHIFT;
			int pointerId = arg1.getPointerId(pointerIndex);
			TouchEvent touchEvent;
			
			switch(action)
			{
			case MotionEvent.ACTION_DOWN:
			case MotionEvent.ACTION_POINTER_DOWN:
				touchEvent = touchEventPool.newObject();
				touchEvent.type = TouchEvent.TOUCH_DOWN;
				touchEvent.pointer = pointerId;
				touchEvent.x = touchX[pointerId] = (int)(arg1.getX(pointerIndex) * scaleX);
				touchEvent.y = touchY[pointerId] = (int)(arg1.getY(pointerIndex) * scaleY);
				isTouched[pointerId] = true;
				touchEventBuffer.add(touchEvent);
				break;
				
			case MotionEvent.ACTION_UP:
			case MotionEvent.ACTION_POINTER_UP:
			case MotionEvent.ACTION_CANCEL:
				touchEvent = touchEventPool.newObject();
				touchEvent.type = TouchEvent.TOUCH_UP;
				touchEvent.pointer = pointerId;
				touchEvent.x = touchX[pointerId] = (int)(arg1.getX(pointerIndex) * scaleX);
				touchEvent.y = touchY[pointerId] = (int)(arg1.getY(pointerIndex) * scaleY);
				isTouched[pointerId] = false;
				touchEventBuffer.add(touchEvent);
				break;
				
			case MotionEvent.ACTION_MOVE:
				int pointerCount = arg1.getPointerCount();
				for(int i=0; i<pointerCount; i++)
				{
					pointerIndex = i;
					pointerId = arg1.getPointerId(pointerIndex);
					touchEvent = touchEventPool.newObject();
					touchEvent.type = TouchEvent.TOUCH_DRAGGED;
					touchEvent.pointer = pointerId;
					touchEvent.x = touchX[pointerId] = (int)(arg1.getX(pointerIndex) * scaleX);
					touchEvent.y = touchY[pointerId] = (int)(arg1.getY(pointerIndex) * scaleY);
				}
				break;
			}
			
		}
		return true;
	}

	@Override
	public boolean isTouchDown(int pointer) {
		// TODO Auto-generated method stub
		synchronized(this)
		{
			if(pointer < 0 || pointer >= 20)
			{
				return false;				
			}
			else
				return isTouched[pointer];
		}
	}

	@Override
	public int getTouchX(int pointer) {
		// TODO Auto-generated method stub
		synchronized(this)
		{
			if(pointer < 0 || pointer >= 20)
			{
				return 0;				
			}
			else
				return touchX[pointer];
		}
	}

	@Override
	public int getTouchY(int pointer) {
		// TODO Auto-generated method stub
		synchronized(this)
		{
			if(pointer < 0 || pointer >= 20)
			{
				return 0;				
			}
			else
				return touchY[pointer];
		}
	}

	@Override
	public List<TouchEvent> getTouchEvents() {
		// TODO Auto-generated method stub
		synchronized(this)
		{
			int len = touchEvents.size();
			
			for(int i=0; i<len; i++)
			{
				touchEventPool.free(touchEvents.get(i));
				touchEvents.clear();
				touchEvents.addAll(touchEventBuffer);
				touchEventBuffer.clear();
				return touchEvents;
			}
		}
		
		return null;
	}
	
}
